<?php

Loader::using("underscore::libs::Doctrine::Lexer");
Loader::using("underscore::libs::Doctrine::Annotations::Annotation::*");
Loader::using("underscore::libs::Doctrine::Annotations::Reader");
Loader::using("underscore::libs::Doctrine::Annotations::*");

/**
 * @Annotation
 */
class Filters {

    /**
     *
     * @var array 
     */
    public $filters = array();

    function __construct($filters) {
        $this->filters = $filters["value"];
    }

}

class FiltersLoader extends AbstractLoader {

    protected function resolveObject($name) {
        $realName = $name . "Filter";
        $path = Loader::toSinglePath("ext::filters::", "");
        $this->checkFile($realName, $path);

        $filter = new $realName();

        if (!($filter instanceof Filter)) {
            throw new Exception("Expected 'Filter' implementor, make sure that class '$realName' implements the 'Filter' interface.");
        }

        return $filter;
    }

}

interface Filter {

    function filter($value, array $params = array());
}

abstract class FilterBase implements Filter {

    public function filter($value, array $params = array()) {
        if (is_array($value)) {
            foreach ($value as &$v) {
                $v = $this->filter($v, $params);
            }
        } else {
            $value = $this->doFilter($value, $params);
        }

        return $value;
    }

    protected abstract function doFilter($value, array $params = array());
}

/**
 * Description of Validator
 *
 * @author JeyDotC
 */
class Validator extends OnSetValue {

    /**
     *
     * @var FiltersLoader 
     */
    private $filtersLoader;

    /**
     *
     * @var Doctrine\Common\Annotations\SimpleAnnotationReader 
     */
    private $annotationReader;

    function __construct() {
        $this->filtersLoader = new FiltersLoader();
        $this->annotationReader = new Doctrine\Common\Annotations\SimpleAnnotationReader();
    }

    public function onSetValue(SetValueEvent $e) {
        /* @var $filterData Filters */
        $filterData = $this->annotationReader->getPropertyAnnotation($e->getProperty(), "Filters");
        if ($filterData) {
            $value = $e->getValue();
            foreach ($filterData->filters as $filter => $params) {
                $value = $this->filtersLoader->load($filter)->filter($value, $params);
            }

            $e->setValue($value);
        }
    }

}

?>
